/**
 * jQuery jfUI (base基本类)
 * 
 * @author yepp(叶平平)
 * @date 2012-11-12
 * 
 * ***/
 
;(function($){
	//jfUI 继承方法
	Function.prototype.jfExtend = function(parent,overrides){
		if(typeof parent != 'function'){
			return this;
		}
		//保存对父类的引用
		this.base = parent.prototype;
        this.base.constructor = parent;
		//继承
		var f = function () { };
        f.prototype = parent.prototype;
        this.prototype = new f();
        this.prototype.constructor = this;
		//附加属性方法
		if(overrides){
			$.extend(this.prototype, overrides);
		}
	};
	//jfUI 延时加载
	Function.prototype.jfDefer = function(o, defer, args){
		var fn = this;
		return  setTimeout(function () { fn.apply(o, args || []); }, defer);
	};
	
	// 核心对象
	window.jf = $.jfui = {
		version : '0.0.0',
		managerCount : 0,
		managers : {},
		managerIdPrev : 'jfui',
		error : {
			managerIsExist: '管理器ID已经存在'
		},
		getId : function(prev){//获取ID
			prev = prev || this.managerIdPrev;
			var id = prev + (1000 + this.managerCount);
			this.managerCount++;
			return id;
		},
		add : function(manager){
			if(arguments.length == 2){
				var m = arguments[1];
				m.id = m.id || m.options.id || arguments[0].id;
                this.addManager(m);
                return; 
			}
			if (!manager.id){
				 manager.id = this.getId(manager.__idPrev());
			} 
            if (this.managers[manager.id]){
            	throw new Error(this.error.managerIsExist);
            }
           this.managers[manager.id] = manager;
		},
		remove : function(arg){
			if(typeof arg == 'string' || arg == 'number'){
				delete $.jfui.managers[arg];
			}else if(typeof arg =='object' && arg instanceof $.jfui.core.Component){
				delete $.jfui.managers[arg.id];
			}
		},
		
		//获取jfui对象
		//1,传入jfui ID ，2,传入Dom Object Array(jQuery)
		get : function(arg,idAttrName){
			idAttrName = idAttrName ||'jfuiid';
			if(typeof arg == 'string' || typeof arg == 'number'){
				return $.jfui.managers[arg];
			}else if(typeof arg=='object' && arg.length){
				if(!arg[0][idAttrName]&&!$(arg[0]).attr(idAttrName)){
					return null;
				}
				return  $.jfui.managers[arg[0][idAttrName] || $(arg[0]).attr(idAttrName)];
			}
			return null;
		},
		//根据类型查找某一个对象
		find : function(type){
			var arr = [];
			for(var id in this.managers){
				var manager = this.managers[id];
				if(type instanceof Function){
					if(manager instanceof type){
						arr.push(manager);
					}
				}else if(type instanceof Array){
					if($.inArray(manager.__getType(),type) != -1){
						arr.push(manager);
					}
				}else{
					if(manager.__getType() == type){
						arr.push(manager);
					}
				}
			}
			return arr;
		},
		//$.fn.jf{Plugin} 和 $.fn.jfGet{Plugin}Manager
        //会调用这个方法,并传入作用域(this)
        //@parm [plugin]  插件名
        //@parm [args] 参数(数组)
        //@parm [ext] 扩展参数,定义命名空间或者id属性名
		run : function(plugin,args,ext){
			if(!plugin){
				return;
			}
			ext = $.extend({
				defaultsNamespace : 'jfDefaults',
				methodsNamespace : 'jfMethods',
				controlNamespace: 'controls',
				idAttrName : 'jfuiid',
				isStatic : false,
				hasElement : true,  //是否拥有element主体(比如drag、resizable等辅助性插件就不拥有)
				propertyToElement : null  //链接到element的属性名
			},ext || {});
			plugin = plugin.replace(/^jfGet/,'');
			plugin = plugin.replace(/^jf/,'');
			if(this == null || this ==window || ext.isStatic){
				if(!$.jfui.plugins[plugin]){
					$.jfui.plugins[plugin] = {
						fn :$['jf'+plugin],
						isStatic : true
					};
				}
				return new $.jfui[ext.controlNamespace][plugin]($.extend({}, $[ext.defaultsNamespace][plugin] || {}, $[ext.defaultsNamespace][plugin + 'String'] || {}, args.length > 0 ? args[0] : {}));
			}
			if(!$.jfui.plugins[plugin]){
				$.jfui.plugins[plugin] = {
					fn: $.fn['jf' + plugin],
					isStatic : false
				};
			}
			if(/Manager$/.test(plugin)){
				return $.jfui.get(this, ext.idAttrName);
			}
			this.each(function(){
				if(this[ext.idAttrName] || $(this).attr(ext.idAttrName)){
					var manager = $.jfui.get(this[ext.idAttrName] || $(this).attr(ext.idAttrName));
					if(manager && args.length>0){
						manager.set(args[0]);
					}//已经执行过
					return;
				}
				if(args.length >= 1 && typeof args[0] == 'string'){
					return;
				}
				 //只要第一个参数不是string类型,都执行组件的实例化工作
				 var options = args.length > 0 ? args[0] : null;
				var p =$.extend({}, $[ext.defaultsNamespace][plugin] || {} , $[ext.defaultsNamespace][plugin + 'String'] || {}, options || {});
				if(ext.propertyToElement){
					p[ext.propertyToElement] = this;
				}
				if(ext.hasElement){
					new $.jfui[ext.controlNamespace][plugin](this, p);
				}else{
					new $.jfui[ext.controlNamespace][plugin](p);
				}
			});
			if(this.length == 0){
				return null;
			}
			if(args.length == 0){
				return $.jfui.get(this,ext.idAttrName);
			}
			if(typeof args[0] == 'object'){
				return $.jfui.get(this,ext.idAttrName);
			}
			if(typeof args[0] == 'string'){
				var manager = $.jfui.get(this,ext.idAttrName);
				if(manager == null){
					return;
				}
				if(args[0] == "option"){
					if(args.length == 2){
						return manager.get(args[1]); // 管理器manager    get
					}else if(args.length >= 3){
						return manager.set(args[1],args[2]); // 管理器manager   set
					}
				}else{
					var method = args[0];
					if(!manager[method]){ //不存在这个方法
						return;
					}
					var params = Array.apply(null,args);
					params.shift();
					return manager[method].apply(manager, params);  //管理器manager method
				}
			}
			return null;
		},
		//扩展
        //1,默认参数     
        //2,本地化扩展 
        defaults: {},
        //3,方法接口扩展
        methods: {},
        //命名空间
        //核心控件,封装了一些常用方法
        core: {},
        //命名空间
        //组件的集合
        controls: {},
        //plugin 插件的集合
        plugins: {}
		
	};
	
	  //扩展对象
    $.jfDefaults = {};

    //扩展对象
    $.jfMethos = {};

    //关联起来
    $.jfui.defaults = $.jfDefaults;
    $.jfui.methods = $.jfMethos;
    
    //获取jfui对象
    //@parm [plugin]  插件名,可为空
    $.fn.jf = function(plugin){
    	if(plugin){
    		return $.jfui.run.call(this,plugin,arguments);
    	}else{
    		return $.jfui.get(this);
    	}
    };
    
    //组件基类
    //1,完成定义参数处理方法和参数属性初始化的工作
    //2,完成定义事件处理方法和事件属性初始化的工作
    $.jfui.core.Component = function(options){
    	//事件容器
    	 this.events = this.events || {};
    	//配置参数
    	 this.options = options || {};
    	//子组件集合索引
    	 this.children = {};
    };
    $.extend($.jfui.core.Component.prototype,{
    	__getType : function(){
    		return '$.jfui.core.Component';
    	},
    	__idPrev : function(){
    		return 'jfui';
    	},
    	//设置属性
    	// arg 属性名    value 属性值 
        // arg 属性/值   value 是否只设置事件
    	set : function(arg,value){
    		if(!arg){
    			return;
    		}
    		if(typeof arg == 'object'){
    			
                var tmp;
                if (this.options != arg){
                    $.extend(this.options, arg);
                    tmp = arg;
                }else{
                    tmp = $.extend({}, arg);
                }
                if (value == undefined || value == true){
                    for (var p in tmp){
                        if (p.indexOf('on') == 0)
                            this.set(p, tmp[p]);
                    }
                }
                if (value == undefined || value == false){
                    for (var p in tmp){
                        if (p.indexOf('on') != 0)
                            this.set(p, tmp[p]);
                    }
                }
                return;
    		}
    		var name = arg;
    		//事件参数
    		if(name.indexOf('on')==0){
    			if(typeof value == 'function'){
    				this.bind(name.substr(2),value);
    			}
    			return;
    		}
    		this.trigger('propertychange',arg,value);
    		if(!this.options){
    			this.options = {};
    		}
    		this.options[name] = value;
    		var pn = '_set'+name.substr(0,1).toUpperCase() + name.substr(1);
    		if(this[pn]){
    			this[pn].call(this,value);
    		}
    		this.trigger('propertychanged',arg,value);
    	},
    	//获取属性
    	get : function(name){
    		var pn = '_get'+name.substr(0,1).toUpperCase() + name.substr(1);
    		if(this[pn]){
    			return this[pn].call(this,name);
    		}
    		return this.options[name];
    	},
    	
    	hasBind : function(arg){
    		var name = arg.toLowerCase();
    		var event = this.events[name];
    		if(event && event.length){
    			return true;
    		}
    		return false;
    	},
    	 //触发事件
        //data (可选) Array(可选)传递给事件处理函数的附加参数
    	trigger : function(arg,data){
    		var name = arg.toLowerCase();
    		var event = this.events[name];
    		if(!event){
    			return;
    		}
    		data = data || [];
    		if((data instanceof Array) == false){
    			data = [data];
    		}
    		for(var i=0; i< event.length; i++){
    			var ev = event[i];
    			if(ev.handler.apply(ev.context,data) == false){
    				return false;
    			}
    		}
    	},
    	 //绑定事件
    	bind : function(arg,handler,context){
    		if(typeof arg == 'object'){
    			for(var p in arg){
    				this.bind(p,arg[p]);
    			}
    			return;
    		}
    		if(typeof handler != 'function'){
    			return false;
    		}
    		var name = arg.toLowerCase();
    		var event = this.events[name] || [];
    		context = context || this;
    		event.push({handler : handler,context:context});
    		this.events[name] = event;
    	},
    	//取消绑定
    	unbind : function(arg,handler){
    		if(!arg){
    			this.events={};
    			return;
    		}
    		var name = arg.toLowerCase();
    		var event = this.event[name];
    		if(!event||!event.length){
    			return;
    		}
    		if(!handler){
    			delete this.events[name];
    		}else{
    			 for (var i = 0, l = event.length; i < l; i++)
                {
                    if (event[i].handler == handler)
                    {
                        event.splice(i, 1);
                        break;
                    }
                }
    		}
    	},
    	destroy : function(){
    		$.jfui.remove(this);
    	}
    });
     //界面组件基类, 
    //1,完成界面初始化:设置组件id并存入组件管理器池,初始化参数
    //2,渲染的工作,细节交给子类实现
    //@parm [element] 组件对应的dom element对象
    //@parm [options] 组件的参数
    $.jfui.core.UIComponent = function(element,options){
    	//调用父类的构造函数 作用域是当前子类 传入options参数 将来options中有什么属性 会为子类构造出什么属性
    	$.jfui.core.UIComponent.base.constructor.call(this, options);;
    	var extendMehods = this._extendMethods();
    	if(extendMehods){
    		$.extend(this,extendMehods);
    	}
    		this.element = element;
    		this._init();
    		this._preRender();
    		this.trigger('render');
    		this._render();
    		this.trigger('rendered');
    		this._rendered();
    	};
    	
    $.jfui.core.UIComponent.jfExtend($.jfui.core.Component,{
    		__getType : function(){
    			return '$.jfui.core.UIComponent';
    		},
    		//扩展方法
    		_extendMethods : function(){
    		
    		},
    		_init : function(){
    			this.type = this.__getType();
    			if(!this.element){
    				this.id = this.options.id || $.jfui.getId(this.__idPrev());
    			}else{
    				this.id = this.options.id ||  this.element.id || $.jfui.getId(this.__idPrev());
    			}
    			//存入管理器池
    			$.jfui.add(this);
    			
    			if(!this.element){
    				return;
    			}
    			
    			//读取attr方法,并加载到参数,比如['url']
    			var attributes = this.attr();
    			if(attributes && attributes instanceof Array){
	    			 for (var i = 0; i < attributes.length; i++){
	                    var name = attributes[i];
	                    this.options[name] = $(this.element).attr(name);
	                }
    			}
    			//读取jfui这个属性，并加载到参数，比如 jfui = "width:120,heigth:100"
    			var p= this.options;
    			if($(this.element).attr('jfui')){
    				try{
    					var attroptons = $(this.element).attr('jfui');
    					if (attroptions.indexOf('{') != 0) attroptions = "{" + attroptions + "}";
                    	eval("attroptions = " + attroptions + ";");
                   		if (attroptions) $.extend(p, attroptions);
    				}catch(e){}
    			}
    		},
    		 //预渲染,可以用于继承扩展
	        _preRender: function (){
	
	        },
	        _render: function (){
	
	        },
	        _rendered: function (){
	            if (this.element)
	            {
	                $(this.element).attr("jfuiid", this.id);
	            }
	        },
	        //返回要转换成jfui参数的属性,比如['url']
	        attr: function (){
	            return [];
	        },
	        destroy: function (){
	            if (this.element) $(this.element).remove();
	            this.options = null;
	            $.jfui.remove(this);
	        }
    	});
   
    
    //表单控件基类
    $.jfui.controls.Input= function (element, options){
    	$.jfui.controls.Input.base.constructor.call(this, element, options);
    };
    $.jfui.controls.Input.jfExtend($.jfui.core.UIComponent,{
    	__getType :function(){
    		return '$.jfui.controls.Input';
    	},
    	attr : function(){
    		 return ['nullText'];
    	},
    	setValue : function(){
    		return this.set('value',value);
    	},
    	getValue : function(){
    		return this.get('value');
    	},
    	setEnabled : function(){
    		return this.set('disabled', false);
    	},
    	setDisabled : function(){
    		return this.set('disabled',true);
    	},
    	updateStyle : function(){
    	
    	}
    });
    
    //全局窗口对象
    $.jfui.win = {
    	//顶端显示
        top: false,
         //遮罩
        mask: function (win){
        	function setHeight(){
        		if(!$.jfui.win.windowMask){
        			return;
        		}
        		var h = $(window).height() + $(window).scrollTop();
        		$.jfui.win.windowMask.height(h);
        		if (!this.windowMask){
	                this.windowMask = $("<div class='l-window-mask' style='display: block;'></div>").appendTo('body');
	                $(window).bind('resize.jfuiwin', setHeight);
	                $(window).bind('scroll', setHeight);
	            }
	            this.windowMask.show();
	            setHeight();
	            this.masking = true;
        	}
        },
         //取消遮罩
        unmask: function (win){
        	var jwins = $("body > .l-dialog:visible,body > .l-window:visible");
            for (var i = 0, l = jwins.length; i < l; i++)
            {
                var winid = jwins.eq(i).attr("jfuiid");
                if (win && win.id == winid){
                	continue;
                } 
                //获取jfui对象
                var winmanager = $.jfui.get(winid);
                if (!winmanager){
                	continue;
                } 
                //是否模态窗口
                var modal = winmanager.get('modal');
                //如果存在其他模态窗口，那么不会取消遮罩
                if (modal){
                	return;
                } 
            }
            if (this.windowMask){
            	this.windowMask.hide();
            }    
            this.masking = false;
        },
         //显示任务栏
        createTaskbar: function (){
        	if (!this.taskbar)
            {
                this.taskbar = $('<div class="l-taskbar"><div class="l-taskbar-tasks"></div><div class="l-clear"></div></div>').appendTo('body');
                if (this.top){
                	this.taskbar.addClass("l-taskbar-top");
                }
                this.taskbar.tasks = $(".l-taskbar-tasks:first", this.taskbar);
                this.tasks = {};
            }
            this.taskbar.show();
            this.taskbar.animate({ bottom: 0 });
            return this.taskbar;
        },
         //关闭任务栏
        removeTaskbar: function ()
        {
            var self = this;
            self.taskbar.animate({ bottom: -32 }, function ()
            {
                self.taskbar.remove();
                self.taskbar = null;
            });
        },
        //激活任务栏
         activeTask: function (win)
        {
            for (var winid in this.tasks)
            {
                var t = this.tasks[winid];
                if (winid == win.id)
                {
                    t.addClass("l-taskbar-task-active");
                }
                else
                {
                    t.removeClass("l-taskbar-task-active");
                }
            }
        },
         //获取任务
        getTask: function (win)
        {
            var self = this;
            if (!self.taskbar){
            	 return;
            }
            if (self.tasks[win.id]){
            	 return self.tasks[win.id];
            }
            return null;
        },
         //增加任务
        addTask: function (win)
        {
            var self = this;
            if (!self.taskbar){
            	 self.createTaskbar();
            }
            if (self.tasks[win.id]){
            	 return self.tasks[win.id];
            }
            var title = win.get('title');
            var task = self.tasks[win.id] = $('<div class="l-taskbar-task"><div class="l-taskbar-task-icon"></div><div class="l-taskbar-task-content">' + title + '</div></div>');
            self.taskbar.tasks.append(task);
            self.activeTask(win);
            task.bind('click', function ()
            {
                self.activeTask(win);
                if (win.actived){
                	win.min();
                }else{
                	win.active();
                }    
            }).hover(function ()
            {
                $(this).addClass("l-taskbar-task-over");
            }, function ()
            {
                $(this).removeClass("l-taskbar-task-over");
            });
            return task;
        },
         hasTask: function ()
        {
            for (var p in this.tasks)
            {
                if (this.tasks[p])
                    return true;
            }
            return false;
        },
         //移除任务
        removeTask: function (win)
        {
            var self = this;
            if (!self.taskbar){
            	 return;
            }
            if (self.tasks[win.id])
            {
                self.tasks[win.id].unbind();
                self.tasks[win.id].remove();
                delete self.tasks[win.id];
            }
            if (!self.hasTask())
            {
                self.removeTaskbar();
            }
        },
        //前端显示
        setFront: function (win)
        {
            var wins = $.jfui.find($.jfui.core.Win);
            for (var i in wins)
            {
                var w = wins[i];
                if (w == win)
                {
                    $(w.element).css("z-index", "9200");
                    this.activeTask(w);
                }
                else
                {
                    $(w.element).css("z-index", "9100");
                }
            }
        }
    };
    //窗口基类 window、dialog
    $.jfui.core.Win = function(element,options){
    	 $.jfui.core.Win.base.constructor.call(this, element, options);
    };
    $.jfui.core.Win.jfExtend($.jfui.core.UIComponent,{
    	 __getType: function (){
    	 	return '$.jfui.controls.Win';
    	 },
    	mask : function(){
    	 	if (this.options.modal){
    	 		$.jfui.win.mask(this);
    	 	}
    	},
    	unmask : function(){
    	 	if (this.options.modal){
    	 		$.jfui.win.unmask(this);
    	 	}
    	},
    	min: function (){
    	},
        max: function (){
        },
        active: function (){
        }
    });
    
    $.jfui.draggable = {
    	dragging: false
    };
    $.jfui.resizable = {
    	 reszing: false
    };
    
    $.jfui.toJSON = typeof JSON === 'object' && JSON.stringify ? JSON.stringify : function (o){
    	 var f = function (n)
        {
            return n < 10 ? '0' + n : n;
        },
		escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
		quote = function (value)
		{
		    escapable.lastIndex = 0;
		    return escapable.test(value) ?
				'"' + value.replace(escapable, function (a)
				{
				    var c = meta[a];
				    return typeof c === 'string' ? c :
						'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
				}) + '"' :
				'"' + value + '"';
		};
        if (o === null){
        	return 'null';
        }
        var type = typeof o;
        if (type === 'undefined'){
        	return undefined;
        }
        if (type === 'string'){
         	return quote(o);
        }
        if (type === 'number' || type === 'boolean'){
        	 return '' + o;
        }
        if (type === 'object')
        {
            if (typeof o.toJSON === 'function')
            {
                return $.jfui.toJSON(o.toJSON());
            }
            if (o.constructor === Date)
            {
                return isFinite(this.valueOf()) ?
                   this.getUTCFullYear() + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate()) + 'T' +
                 f(this.getUTCHours()) + ':' +
                 f(this.getUTCMinutes()) + ':' +
                 f(this.getUTCSeconds()) + 'Z' : null;
            }
            var pairs = [];
            if (o.constructor === Array)
            {
                for (var i = 0, l = o.length; i < l; i++)
                {
                    pairs.push($.jfui.toJSON(o[i]) || 'null');
                }
                return '[' + pairs.join(',') + ']';
            }
            var name, val;
            for (var k in o)
            {
                type = typeof k;
                if (type === 'number')
                {
                    name = '"' + k + '"';
                } else if (type === 'string')
                {
                    name = quote(k);
                } else
                {
                    continue;
                }
                type = typeof o[k];
                if (type === 'function' || type === 'undefined')
                {
                    continue;
                }
                val = $.jfui.toJSON(o[k]);
                pairs.push(name + ':' + val);
            }
            return '{' + pairs.join(',') + '}';
        }
    };
})(jQuery);
